import { HttpException, HttpStatus, Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Workbook } from 'exceljs'
import { DataSource, FindOneOptions, Repository } from 'typeorm'
import { PlayerUser } from '@/modules/user/entities/player-user.entity'
import { FindSubscribeDto, ListPageSubscribeDto, ListPageSubscribeVo, UpdateSubscribeDto } from './dto/subscribe.dto'
import { Subscribe } from './entities/subscribe.entity'

@Injectable()
export class SubscribeService {
  constructor(
    @InjectRepository(Subscribe)
    private subscribeRepository: Repository<Subscribe>,
    private readonly dataSource: DataSource,
  ) {}

  create(createData: Partial<Subscribe>) {
    return this.subscribeRepository.save({ ...createData, subscribeId: undefined })
  }

  async customFind(options: FindOneOptions<Subscribe>) {
    return await this.subscribeRepository.find(options)
  }

  async findOne(data: FindSubscribeDto) {
    return await this.subscribeRepository.findOne({ where: { ...data, isDeleted: false }, relations: ['subscribeUserInfo', 'inviteUserInfo'] })
  }

  async findPage(query: ListPageSubscribeDto): Promise<ListPageSubscribeVo> {
    const { pageNo = 1, pageSize = 10, ...rest } = query
    const [list, total] = await this.subscribeRepository.findAndCount({
      where: { ...rest, isDeleted: false },
      skip: (pageNo - 1) * pageSize,
      take: pageSize,
      relations: ['subscribeUserInfo', 'inviteUserInfo'],
      order: {
        createdAt: 'DESC',
      },
    })

    return {
      total,
      list,
    }
  }

  async findList(data: FindSubscribeDto) {
    return await this.subscribeRepository.find({
      where: { ...data, isDeleted: false },
      relations: ['subscribeUserInfo', 'inviteUserInfo'],
      order: {
        createdAt: 'DESC',
      },
    })
  }

  async update(subscribeId: number, updateData: UpdateSubscribeDto) {
    return this.subscribeRepository.update(subscribeId, {
      ...updateData,
      subscribeId: undefined,
    })
  }

  async removeAndUpdateUserSubscribe(subscribeId: number) {
    return await this.dataSource.transaction(async (manager) => {
      const findData = await manager.findOne(Subscribe, {
        where: { subscribeId, isDeleted: false },
        relations: ['subscribeUserInfo'],
      })
      if (!findData) {
        throw new HttpException('预约不存在', HttpStatus.NOT_FOUND)
      }

      // await manager.delete(Subscribe, subscribeId)
      await manager.update(Subscribe, { subscribeId }, { isDeleted: true })
      await manager.update(PlayerUser, { uid: findData.subscribeUserInfo.uid }, { isReserved: false })
    })
  }

  async export(): Promise<ArrayBuffer> {
    // 查询数据
    const data = await this.subscribeRepository.find({
      where: { isDeleted: false },
      relations: ['subscribeUserInfo', 'inviteUserInfo'],
    })

    // 创建 workbook
    const workbook = new Workbook()
    const worksheet = workbook.addWorksheet('订阅数据')

    // 表头
    worksheet.columns = [
      {
        header: '手机号',
        key: 'subscribePhone',
        width: 20,
        style: { alignment: { horizontal: 'left' } },
      },
      {
        header: '问卷最高得分',
        key: 'questionScore',
        width: 15,
        style: { alignment: { horizontal: 'left' } },
      },
      {
        header: '是否老玩家',
        key: 'isOldPlayer',
        width: 12,
        style: { alignment: { horizontal: 'left' } },
      },
      {
        header: '邀请人手机号',
        key: 'invitePhone',
        width: 20,
        style: { alignment: { horizontal: 'left' } },
      },
      {
        header: '邀请人 UID',
        key: 'inviteUserUid',
        width: 12,
        style: { alignment: { horizontal: 'left' } },
      },
      { header: '预约时间', key: 'createdAt', width: 20, style: { alignment: { horizontal: 'left' } } },
    ]

    // 写入数据
    data.forEach((item) => {
      worksheet.addRow({
        subscribePhone: item.subscribePhone,
        createdAt: item.createdAt,
        questionScore: item.subscribeUserInfo?.questionScore,
        isOldPlayer: item.subscribeUserInfo?.questionScore > 70 ? '是' : '否',
        invitePhone: item.inviteUserInfo?.phone,
        inviteUserUid: item.inviteUserUid,
      })
    })

    // 生成 buffer
    return await workbook.xlsx.writeBuffer()
  }
}
